package com.ztesoft.web.checkup.service.impl;

import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import javax.sql.DataSource;

import org.apache.commons.net.ftp.FTPClient;
import org.springframework.beans.factory.annotation.Autowired;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.ztesoft.core.db.ds.DynamicDataSourceManager;
import com.ztesoft.core.spring.context.SpringApplicationContextHolder;
import com.ztesoft.framework.exception.BaseAppException;
import com.ztesoft.framework.exception.ExceptionHandler;
import com.ztesoft.framework.log.ZTEsoftLogManager;
import com.ztesoft.framework.util.DateUtils;
import com.ztesoft.iocp.cipher.util.RSAUtils;
import com.ztesoft.web.baseconfig.db.arg.DmTargetTableArg;
import com.ztesoft.web.baseconfig.db.dao.DmTargetTableDao;
import com.ztesoft.web.baseconfig.db.po.DmPlanPO;
import com.ztesoft.web.baseconfig.db.po.DmSrcTablePO;
import com.ztesoft.web.baseconfig.db.po.DmStrategyPO;
import com.ztesoft.web.baseconfig.db.po.DmTargetTablePO;
import com.ztesoft.web.checkup.service.CheckUpStrategy;
import com.ztesoft.web.common.DMSConstant;
import com.ztesoft.web.common.FtpClientHelper;
import com.ztesoft.web.common.SubTableDefine;
import com.ztesoft.web.common.Util;
import com.ztesoft.web.common.customdb.dao.DmTaskStageCustomDao;
import com.ztesoft.web.common.customdb.dao.dto.DmTaskStageDto;
import com.ztesoft.web.common.db.arg.DmDataCommandArg;
import com.ztesoft.web.common.db.arg.DmProcedureArg;
import com.ztesoft.web.common.db.dao.DmDataCommandDao;
import com.ztesoft.web.common.db.dao.DmProcedureDao;
import com.ztesoft.web.common.db.po.DmDataCommandPO;
import com.ztesoft.web.common.db.po.DmProcedurePO;
import com.ztesoft.web.common.vo.HostConnInfoVO;
import com.ztesoft.web.common.vo.HostConnMethodVO;
import com.ztesoft.web.resourcecheck.ResourceCheckJob;
import com.ztesoft.web.syncbaseinfo.service.BaseInfoService;
import com.ztesoft.web.taskgenerator.db.dao.DmTaskDao;
import com.ztesoft.web.taskgenerator.db.po.DmTaskPO;


/**
 * 体检策略<br>
 * 整表执行体检
 * 
 * @author <a href="mailto:lin.weibin@zte.com.cn">lin.wb</a> 2016年5月19日 下午7:13:20
 * @version 1.0
 */
public class CheckUpStrategyWhole implements CheckUpStrategy {
	
	private static final ZTEsoftLogManager LOGGER = ZTEsoftLogManager
	            .getLogger(CheckUpStrategyWhole.class);
	
	@Autowired
	private DynamicDataSourceManager dynamicDataSourceManager;
	
	@Autowired
	private BaseInfoService baseInfoService;
	
	@Autowired
	private DmTaskStageCustomDao taskStageCustomDao;

	@Autowired
	private ResourceCheckJob resourceCheckJob;
	
	@Autowired
	private DmTaskDao taskDao;
	
	@Autowired
	private DmTargetTableDao targetTableDao;
	
	@Autowired
	private DmProcedureDao dmProcedureDao;
	
	@Autowired
	private DmDataCommandDao dmDataCommandDao;
	
	@Autowired
	private SubTableDefine subTableDefine;
	
	public String checkUp(DmPlanPO planPO, DmTaskPO taskPO, DmStrategyPO strategyPO, DmSrcTablePO srcTablePO) {
		
		String checkState = "00A";
		LOGGER.debug("|查询任务环节列表|strategyId={0},taskId={1}", strategyPO.getDmStrategyId(), taskPO.getDmTaskId());
		List<DmTaskStageDto> taskStageList = taskStageCustomDao.selectTaskStageList(taskPO.getDmTaskId(), 
				strategyPO.getDmStrategyId(), DMSConstant.STAGE_CHECKUP, DMSConstant.Status.PENDING.getState());
		LOGGER.info("|查询待体检任务环节列表|\r\n{0}",taskStageList);
		if (taskStageList.isEmpty()) {
			return checkState;//
		}

		for (DmTaskStageDto taskStagePO : taskStageList) {			
			taskStagePO.setTaskStartTime((taskStagePO.getTaskStartTime()!=null)?null:DateUtils.getDBCurrentTime());
			taskStagePO.setTaskEndTime(null);//避免带入条件
			taskStagePO.setCheckDataSize(null);
			taskStagePO.setErrorDesc(null);
			taskStagePO.setStage(null);
			taskStagePO.setState(DMSConstant.Status.PROCESSING.getState());
			taskStageCustomDao.updateTaskStageState(taskStagePO);
		}
		
		/*
		 * 全表归档 
		 * a、同数据库归档，执行存储过程
		 * b、跨同类型数据库，导出导入命令
		 * c、跨类型数据库，普通条件归档
		 */
		String[] srcDbConfig = null;
		String[] targetDbConfig = null;
		DmTargetTableArg dmTargetTableArg = new DmTargetTableArg();
		DmTargetTableArg.DmTargetTableCriteria targetTableCriteria = dmTargetTableArg.createCriteria();
		targetTableCriteria.andSourceDataIdEqualTo(srcTablePO.getSourceDataId());
		DmTargetTablePO targetPO = targetTableDao.selectByArg(dmTargetTableArg).get(0);
		try {
			srcDbConfig = baseInfoService.getDbConfig(srcTablePO.getDbLinkId(), srcTablePO.getDbUserName());
			targetDbConfig = baseInfoService.getDbConfig(targetPO.getDbLinkId(), targetPO.getDbUserName());
		} catch (BaseAppException skip) {}
		
		if (srcDbConfig[0].equalsIgnoreCase(targetDbConfig[0])) {//数据库类型一致
			if (Arrays.equals(srcDbConfig, targetDbConfig)) {//a、同数据库归档，执行存储过程
				String param = subTableDefine.initTableNameParam(srcTablePO, taskPO.getNodeId(), planPO.getDmPlanId());
				checkState = execProdure(srcTablePO, taskStageList, srcDbConfig, targetPO, param);
			} else {
				//b、跨同类型数据库，导出导入命令 truncate DM_DATA_COMMAND 
				checkState = execImpExp(srcTablePO, srcDbConfig, targetPO);
			}
		} else {
			//c、夸类型数据库，普通条件归档
			CheckUpStrategy checkUpStrategy = SpringApplicationContextHolder.getBean(CheckUpStrategyCondition.class);
			checkState = checkUpStrategy.checkUp(planPO, taskPO, strategyPO, srcTablePO);
		}
		return checkState;
		
	}

	@SuppressWarnings("unchecked")
	private String execProdure(DmSrcTablePO srcTablePO,
			List<DmTaskStageDto> taskStageList, String[] srcDbConfig, DmTargetTablePO targetTablePO, String param) {
		String checkState = "50E";
		try {
			
			if (srcTablePO.getUpperOffset() == null) {
				srcTablePO.setUpperOffset(-1);
			}
			if (srcTablePO.getLowerOffset() == -9) {
				srcTablePO.setLowerOffset(-1);
			}
			
			DmProcedureArg dmProcedureArg = new DmProcedureArg();
			DmProcedureArg.DmProcedureCriteria dmProcedureCriteria = dmProcedureArg.createCriteria();
			dmProcedureCriteria.andSourceDataIdEqualTo(srcTablePO.getSourceDataId());
			dmProcedureCriteria.andStateEqualTo("00A");
			DmProcedurePO dmProcedurePO = dmProcedureDao.selectByArg(dmProcedureArg).get(0);
			String result = null;
			DataSource srcDataSource = dynamicDataSourceManager.getDruidDataSource(srcTablePO.getDbLinkId()+srcTablePO.getDbUserName(), srcDbConfig);
			if (DMSConstant.BACK_UP_PARAM.equals(dmProcedurePO.getProcedureName())) {
				CheckUpByProcTransable checkUpByProcTime = 
						(CheckUpByProcTransable) SpringApplicationContextHolder.getBean("checkUpByProcTransable");
				if ("oracle".equals(srcDbConfig[0])) {					
					result = checkUpByProcTime.execProcTransable(srcDataSource, 
							srcTablePO.getTableName(), targetTablePO.getTableName(), param.length() == 0 ? "-9" : param);
				} else {
					result = checkUpByProcTime.execNormalProcTransable(srcDataSource, srcTablePO.getTableName(), targetTablePO.getTableName(), param.length() == 0 ? "-9" : param);
				}
			} else if (DMSConstant.BACK_UP_TIME.equals(dmProcedurePO.getProcedureName())){
				CheckUpByProcTime checkUpByProcTime = 
						(CheckUpByProcTime) SpringApplicationContextHolder.getBean("checkUpByProcTime");
				if ("oracle".equals(srcDbConfig[0])) {		
					result = checkUpByProcTime.execProcTime(srcDataSource, srcTablePO.getTableName(), 
							targetTablePO.getTableName(), srcTablePO.getUpperOffset(), srcTablePO.getLowerOffset(), param.length() == 0 ? -1 : Integer.parseInt(param));
				} else {					
					result = checkUpByProcTime.execNormalProcTime(srcDataSource, srcTablePO.getTableName(), 
							targetTablePO.getTableName(), srcTablePO.getUpperOffset(), srcTablePO.getLowerOffset(), param.length() == 0 ? -1 : Integer.parseInt(param));
				}
			}
			LOGGER.info("执行结果{0}", result);
			JSONObject jsonObject = JSON.parseObject(result);
			if (jsonObject.containsKey("error")) {
				throw ExceptionHandler.publish("执行异常",jsonObject.getString("error"));
			}
			Map<String,String> map  = (Map<String, String>) jsonObject.get("result");
			for (DmTaskStageDto po : taskStageList) {
				if (!map.containsKey(po.getCheckObjName())) continue;
				po.setTaskStartTime(null);
				po.setState("00A");
				po.setStateDate(DateUtils.getDBCurrentTime());
				po.setTaskEndTime(DateUtils.getDBCurrentTime());
				po.setStage(null);
				po.setErrorDesc(null);
				po.setIsCheck(0);//默认审批通过
				po.setCheckCount(Integer.parseInt(map.get(po.getCheckObjName())));
				po.setTotalRecordCount(Integer.parseInt(map.get(po.getCheckObjName())));
				po.setCheckDataSize(Util.divValue2BigDecimal(srcTablePO.getOneRecordSize(), po.getTotalRecordCount(), 2));
				po.setTotalDataSize(po.getCheckDataSize());
				taskStageCustomDao.updateTaskStageState(po);//
				checkState = "50E";
			}
		} catch (Exception e) {
			LOGGER.error("——", e);
			checkState = DMSConstant.Status.FALSE.getState();
			DmTaskStageDto po = taskStageList.get(0);
			po.setTaskStartTime(DateUtils.getDBCurrentTime());
			po.setState(checkState);
			po.setStateDate(DateUtils.getDBCurrentTime());
			po.setTaskEndTime(DateUtils.getDBCurrentTime());
			po.setCheckObjName(null);//更新策略下所有
			po.setStage(null);
			po.setErrorDesc(e.getLocalizedMessage());
			taskStageCustomDao.updateTaskStageState(po);//
		}
		return checkState;
	}

	
	//TODO
	private String execImpExp(DmSrcTablePO srcTablePO, String[] srcDbConfig, DmTargetTablePO targetPO) {
		DmDataCommandArg dmDataCommandArg = new DmDataCommandArg();
		DmDataCommandArg.DmDataCommandCriteria dmDataCommandCriteria = dmDataCommandArg.createCriteria();
		dmDataCommandCriteria.andSourceDataIdEqualTo(srcTablePO.getSourceDataId());
		dmDataCommandCriteria.andStateEqualTo("00A");
		dmDataCommandCriteria.andCommandTypeBetween(0, 1);
		dmDataCommandArg.setOrderByClause("command_type");
		List<DmDataCommandPO> dmDataCommandPOs = dmDataCommandDao.selectByArg(dmDataCommandArg);
		DmDataCommandPO dmDataCommandPO = null;
		
		//获取主机连接信息
		HostConnInfoVO hostConnInfoVO = null;
		try {
			hostConnInfoVO = baseInfoService.qryHostConn(dmDataCommandPOs.get(0).getDbLinkId());
		} catch (BaseAppException skip) {}
		List<HostConnMethodVO> hostConnMethodVOList = hostConnInfoVO.getHostConnMethod();
		boolean result = false;
		Map<String, HostConnMethodVO> HostConnMethodMap = new HashMap<String, HostConnMethodVO>();
		for (int i = 0, j = hostConnMethodVOList.size(); i < j; i++) {//链接		//TODO 归档方式
			if (hostConnMethodVOList.get(i).getConnMethod().equals(DMSConstant.HOST_LINK_TELNET)) {
				HostConnMethodMap.put(DMSConstant.HOST_LINK_TELNET, hostConnMethodVOList.get(i));
			} 
			try {
				 FTPClient ftpClient = FtpClientHelper.openFtpServer(hostConnInfoVO.getIp(),
						hostConnMethodVOList.get(i).getPort(),
						hostConnMethodVOList.get(i).getUserName(),
						RSAUtils.decryptString(hostConnMethodVOList.get(i).getPassword()));
			} catch (BaseAppException e) {
				LOGGER.error(e.getCode(),e);
				LOGGER.error("",hostConnMethodVOList.get(i));
				continue;
			}
			result = true;
			break;
		}
		//分数据库执行操作
		if (srcDbConfig[0].equalsIgnoreCase("oracle")) {
//				--导出
//				exp username/password@dbname file=d:datanewsmgnt.dmp tables=(tablename1,tablename2)
//				String fileName = "E:\\doc\\dms\\test";
//				StringBuilder expBuilder = new StringBuilder("exp ");
//				expBuilder.append(dbConfig[2]).append("/").append(dbConfig[3]).append("@")
//					.append(dbConfig[4]).append(" file=").append(fileName).append(".dmp tables=(")
//					.append(src.getTableName()).append(")  FULL=Y");
//				--导入
//				imp username/password@dbname  full=y file=d:datanewsmgnt.dmp ignore=y
			dmDataCommandPO = dmDataCommandPOs.get(0);
			String expCommand = dmDataCommandPO.getCommand();
			expCommand = expCommand.replace("$1", srcDbConfig[2]);
			expCommand = expCommand.replace("$2", srcDbConfig[3]);
			expCommand = expCommand.replace("$3", dmDataCommandPO.getAliasLinkName());
			expCommand = expCommand.replace("$4", srcTablePO.getTableName());
			try {//执行导出 TODO
//						if (map.get("result").contains("successfully")) {
//							String countStr = map.get("result").substring(map.get("result").
//									indexOf(srcTablePO.getTableName().toUpperCase())+srcTablePO.getTableName().length(),
//									map.get("result").indexOf("rows")).trim();
//							//更新表 体检数据
//							break;
//						} else if (map.get("result").contains("successfully")) {
//							//更新执行失败
//						} 
			} catch (Exception e) {
				e.printStackTrace();
			}
//				result = FtpClientHelper.gotoRemotePath(ftpClient, remoteDir);
//				result = FtpClientHelper.getFile(ftpClient, reomteFileName, localFilePathName);
//				result = FtpClientHelper.gotoRemotePath(ftpClient, ftpPath);
//				result = FtpClientHelper.putFile(ftpClient, remoteFileName, localPathFileName);
			String impCommand = dmDataCommandPOs.get(0).getCommand();
			impCommand = impCommand.replace("$1", srcDbConfig[2]);
			impCommand = impCommand.replace("$2", srcDbConfig[3]);
			impCommand = impCommand.replace("$3", dmDataCommandPO.getAliasLinkName());
			impCommand = impCommand.replace("$4", targetPO.getTableName());
//					try {//执行导入
//						Runtime.getRuntime().exec(impCommand);
//					} catch (IOException e) {
//						e.printStackTrace();
//					}
		} else if (srcDbConfig[0].equalsIgnoreCase("informix")) {
			
		} else if (srcDbConfig[0].equalsIgnoreCase("mysql")) {
			
		}
		return "50E"; 
		
		
	}
}
